/**
 * Licensed to Open-Ones Group under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Open-Ones Group licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a
 * copy of the License at:
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package openones.ipresenter.android.view;

import openones.ipresenter.android.R;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.os.CountDownTimer;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;

/**
 * This is a custom view used for handling gestures within it.
 * @author OOG member
 */
public class SlideView extends View {     
    /**
     * Used to pad the bitmap 30 to the left and from the bottom.
     */
    private static final int BITMAP_PADDING = 30;
    
    /**
     * The number of millis in the future from the call to start() 
     * until the countdown is done and onFinish() is called.
     */
    private static final int COUNT_DOWN_TIME = 200;
    
    /**
     * The interval along the way to receive onTick(long) callbacks. 
     */
    private static final int COUNT_DOWN_INTERVAL = 100;
    
    /**
     * Constant indicates there is not bitmap to be drawn.
     */
    public static final int BITMAP_NONE = 0;
    
    
    /**
     * Constant indicates that the current bitmap is "next" bitmap.
     */
    private static final int BITMAP_NEXT = 1;
    
    /**
     * Constant indicates that the current bitmap is "previous" bitmap.
     */
    private static final int BITMAP_PREVIOUS = 2;
    
    /**
     * Constant indicates that the current bitmap is "full screen" bitmap.
     */
    private static final int BITMAP_FULLSCREEN = 3;
    
    /**
     * Constant indicates that the current bitmap is "exit full screen" bitmap.
     */
    private static final int BITMAP_EXIT_FULLSCREEN = 4;
    
    /**
     * Used to detect common user motions.
     */
    private GestureDetector mGestureDetector;
    
    /**
     * PresentActivity context.
     */
    private Context mContext;
    
    /**
     * The current bitmap.
     */
    private int mBitmap;
    
    /**
     * The "next" bitmap to show when flinging next.
     */
    private Bitmap mBitmapNext;
    
    /**
     * The "previous" bitmap when fling previous.
     */
    private Bitmap mBitmapPrevious;
    
    /**
     * The "full screen" bitmap when double tapping.
     */
    private Bitmap mBitmapFullScreen;
    
    /**
     * The "exit full screen" bitmap when long pressing.
     */
    private Bitmap mBitmapExitFullScreen;
    
    
    
    /**
     * Constructor.
     * @param context The PresentActivity context.
     */
    public SlideView(Context context) {
        super(context);

        GestureListener listener = new GestureListener(this);
        mGestureDetector = new GestureDetector(context, listener);
        mContext = context;
        
        setmBitmap(BITMAP_NONE);
        mBitmapNext = BitmapFactory.decodeResource(getResources(), R.drawable.button_next_pressed);
        mBitmapPrevious = BitmapFactory.decodeResource(getResources(), R.drawable.button_previous_pressed);
        mBitmapFullScreen = BitmapFactory.decodeResource(getResources(), R.drawable.button_fullscreen_pressed);
        mBitmapExitFullScreen = BitmapFactory.decodeResource(getResources(), R.drawable.button_exitfullscreen_pressed);
    }
    
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean result = false;
        // mGestureDetector gets and recognizes the event.
        result = mGestureDetector.onTouchEvent(event);
        return result;
    }
    
    /**
     * Respond to gesture "fling left to right".
     */
    public void onGestureNext() {
        setmBitmap(BITMAP_NEXT);
        displayBitmap();
        ((PresentActivity) mContext).sendCommandNext();
    }
    
    /**
     * Respond to gesture "fling right to left".
     */
    public void onGesturePrevious() {
        setmBitmap(BITMAP_PREVIOUS);
        displayBitmap();
        ((PresentActivity) mContext).sendCommandPrevious();
    }
    
    /**
     * Respond to gesture "double tap".
     */
    public void onGestureFullSreen() {
        setmBitmap(BITMAP_FULLSCREEN);
        displayBitmap();
        ((PresentActivity) mContext).sendCommandFullScreen();
    }
    
    /**
     * Respond to gesture "long press".
     */
    public void onGestureExitFullSreen() {
        setmBitmap(BITMAP_EXIT_FULLSCREEN);
        displayBitmap();
        ((PresentActivity) mContext).sendCommandExitFullScreen();
    }
    
    @Override
    protected void onDraw(Canvas canvas) {
        Matrix translate = new Matrix();
        translate.setTranslate(BITMAP_PADDING, BITMAP_PADDING);
        
        switch (getmBitmap()) {
        case BITMAP_NEXT:
            if (mBitmapNext != null) {
                canvas.drawBitmap(mBitmapNext, translate, null);
            }
            break;
        case BITMAP_PREVIOUS:
            if (mBitmapPrevious != null) {
                canvas.drawBitmap(mBitmapPrevious, translate, null);
            }
            break;
        case BITMAP_FULLSCREEN:
            if (mBitmapFullScreen != null) {
                canvas.drawBitmap(mBitmapFullScreen, translate, null);
            }
            break;
        case BITMAP_EXIT_FULLSCREEN:
            if (mBitmapExitFullScreen != null) {
                canvas.drawBitmap(mBitmapExitFullScreen, translate, null);
            }
            break;
        default:
            break;
        
        }
    }
    
    /**
     * Start the Count down timer to show the current bitmap for a short time.
     */
    void displayBitmap() {
        // Cause the canvas to redraw, so that the current bitmap can be drawn.
        invalidate();
        
        CountDownTimer countDownTimer = new CountDownTimer(COUNT_DOWN_TIME, COUNT_DOWN_INTERVAL) {
            public void onTick(long millisUntilFinished) {
                
            }

            public void onFinish() {
                setmBitmap(BITMAP_NONE);
                // Make the current bitmap disappear.
                // Cause the canvas to redraw, so that the SlideView is blank.
                invalidate();
            }
         };
         countDownTimer.start();
        

    }
    
    /**
     * Set the mBitmap.
     * @param mBitmap The bitmap to set.
     */
    private void setmBitmap(int mBitmap) {
        this.mBitmap = mBitmap;
    }

    /**
     * Get the mBitmap.
     * @return mBitmap.
     */
    public int getmBitmap() {
        return mBitmap;
    }


    /**
     * Listen and respond to any gestures recognized by GestureDetector.
     * @author KhoaPD
     */
    private class GestureListener extends GestureDetector.SimpleOnGestureListener {
        /**
         * The SlideView.
         */
        private SlideView mView;
        
        /**
         * Make sure the fling is with at least certain length of touch duration.
         */
        private static final int SWIPE_MIN_DISTANCE = 80;
        
        /**
         * Make sure the fling is with certain velocity.
         */
        private static final int SWIPE_THRESHOLD_VELOCITY = 40;
        
        /**
         * Constructor.
         * @param view The SlideView
         */
        public GestureListener(SlideView view) {
            this.mView = view;
        }
        
        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }
        
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, final float velocityX, final float velocityY) {
            // User fling right to left.
            if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                mView.onGesturePrevious();
            
                // User fling left to right.
            } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                mView.onGestureNext();
            }
            
            return true;
        }
        
        @Override
        public boolean onDoubleTap(MotionEvent e) {    
            mView.onGestureFullSreen();
            return true;
        }
        
        @Override
        public void onLongPress(MotionEvent e) {     
            mView.onGestureExitFullSreen();     
            
        }
        
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            return true;
        }
    }
    
    
}

